package com.zdy.im.tio.command.handler;

import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.sixeco.framework.common.api.ApiDoc;
import com.sixeco.framework.common.enums.SysResultCodeEnum;
import com.sixeco.framework.common.enums.TbStatusEnum;
import com.sixeco.framework.core.redis.RedisClusterServer;
import com.sixeco.framework.core.redis.RedisKeys;
import com.sixeco.framework.core.redis.RedisUtil;
import com.sixeco.framework.http.exception.SystemRuntimeException;
import com.sixeco.framework.util.ids.GlobalId;
import com.sixeco.framework.util.json.JsonUtils;
import com.zdy.im.chat.ChatMessageBody;
import com.zdy.im.chat.ChatMessageEnum;
import com.zdy.im.chat.ChatMessageInfo;
import com.zdy.im.common.exception.ImException;
import com.zdy.im.core.ICommand;
import com.zdy.im.enums.ImMessageTypeEnum;
import com.zdy.im.tio.TioServerConfig;
import com.zdy.im.tio.command.AbstractCommandHandler;
import com.zdy.im.tio.command.Command;
import com.zdy.im.tio.command.ProtocolManager;
import com.zdy.im.tio.packets.*;
import com.zdy.im.user.dto.request.ImChatMessageRequestDto;
import com.zdy.im.user.dto.request.ImJoinFriendStatusRequestDto;
import com.zdy.im.user.dto.request.ImRoomChatMessageRequestDto;
import com.zdy.im.user.dto.request.ImUserFriendShipRequestDto;
import com.zdy.im.user.dto.response.*;
import com.zdy.im.user.service.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.core.intf.Packet;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;

import java.util.Date;


/**
 * 同意添加好友消息命令处理器
 * @author zhangdayong
 * @date 2021年6月2日 下午2:40:07
 */
@Component
@ApiDoc(module = "WebSocket 项目文档",group = "SOCKET-GROUP")
public class AgreeFridendRequestHandler extends AbstractCommandHandler {

	private static Logger logger = LoggerFactory.getLogger(AgreeFridendRequestHandler.class);

	@Autowired
	private ImUserFriendShipService imUserFriendShipService;
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private ImUserGroupInfoService imUserGroupInfoService;
	@Autowired
	private ImJoinFriendService imJoinFriendService;
	@Autowired
	private ImChatMessageService imChatMessageService;
	@Autowired
	private RedisClusterServer redisClusterServer;

	@Override
	public ICommand command() {
		return Command.COMMAND_FRIEND_AGREE_MESSAGE_REQ;
	}
	public ICommand responseCmd() {
		return Command.COMMAND_FRIEND_AGREE_MESSAGE_RESP;
	}

	@ApiDoc(
			cmd = "21",methodType = "ws",
			value = "同意添加好友协议 cmd=21",
			request = AgreeFriendRequestVo.class,
			response = ChatMessageBody.class
	)
	@Override
	public Packet handler(Packet wsPacket, ChannelContext channelContext) throws ImException {
		logger.info("进入通过好友添加 handler!!!");
		//推送好友添加通过;
		WsRequest packet = (WsRequest) wsPacket;

		if (packet.getBody() == null) {
			throw new ImException("body is null");
		}
		AgreeFriendRequestVo agreeVo = JsonUtils.parseObject(packet.getWsBodyText(), AgreeFriendRequestVo.class);
		if (agreeVo == null || agreeVo.getMessage() == null) {
			logger.info(" 添加好友参数错误 !!! ");
			Packet respChatPacket = ProtocolManager.ResponsePacket.dataInCorrect(channelContext,responseCmd());
			return respChatPacket;
		}
		long userId = agreeVo.getMessage().getSendUserId();
		long friendId = agreeVo.getMessage().getToId();
		if(userId == 0 || friendId ==0 || userId == friendId){
			logger.info(" 不能添加自己 !!! userId = {}, friend = {}",userId ,friendId);
			Packet respChatPacket = ProtocolManager.ResponsePacket.dataInCorrect(channelContext,responseCmd());
			return respChatPacket;
		}
		ChatMessageEnum enums = ChatMessageEnum.getEnum(agreeVo.getType());
		if(enums == null){
			logger.info(" 发送信息的代码类型错误 !!! ");
			Packet respChatPacket = ProtocolManager.ResponsePacket.dataInCorrect(channelContext,responseCmd());
			return respChatPacket;
		}

		//todo  绑定用户与好友关系
		if(!checkBindUserFriend(userId, friendId, agreeVo.getRemarks())){
			Packet respChatPacket = ProtocolManager.ResponsePacket.dataInCorrect(channelContext,responseCmd());
			return respChatPacket;
		}

		//消息体
		ChatMessageBody message = ChatMessageBody.build().clone(agreeVo.getMessage());
		//todo  聊天记录
		if(!saveMessage(message, agreeVo, enums)){
			return ProtocolManager.ResponsePacket.dataInCorrect(channelContext,responseCmd());
		}
		//聊天记录保存redis
		saveRedis(message);

		boolean isOnline = super.isOnline(channelContext, String.valueOf(friendId));
		logger.info("绑定好友成功 handler!!! isOnline = {}",isOnline);
		if (isOnline) {
			WsResponse wsResponse = WsResponse.fromText(JsonUtils.toJson(message), TioServerConfig.CHARSET);
			Tio.sendToUser(channelContext.tioConfig, String.valueOf(friendId), wsResponse);
			return ProtocolManager.ResponsePacket.success(channelContext,responseCmd());
		}
		//离线发送
		return ProtocolManager.ResponsePacket.offline(channelContext, responseCmd());
	}

	/**
	 * 绑定用户与好友关系
	 * @param userId
	 * @param friendId
	 * @param remark
	 * @return
	 */
	private boolean checkBindUserFriend(long userId, long friendId, String remark){
		ImUserFriendShipResponseDto userFriendShipDto = imUserFriendShipService.selectFriend(userId, friendId);
		if(userFriendShipDto != null){
			logger.info(" 该用户已经添加过该好友 !!! userId = {}, friendId = {}",userId,friendId);
			return false;
		}
		//查询用户存不存在
		UserInfoResponseDto userInfoResponseDto = userInfoService.getUserInfoById(userId);
		if (null == userInfoResponseDto){
			logger.info(" 该用户信息不存在 !!! userId = {}",userId);
			return false;
		}

		//查询好友存不存在
		UserInfoResponseDto userFriendInfoResponseDto = userInfoService.getUserInfoById(friendId);
		if (null == userFriendInfoResponseDto){
			logger.info(" 该好友信息不存在 !!! friendId = {}",friendId);
			return false;
		}

		//获取默认组
		ImUserGroupInfoResponseDto imUserGroupInfoResponseDto = imUserGroupInfoService.selectDefGroupOne(userId);
		if(imUserGroupInfoResponseDto == null ){
			logger.info(" 该用户默认组信息不存在 !!! userId = {}",userId);
			return false;
		}

		//双绑定操作

		//1.好友与用户关系操作
		//获取好友默认组
		ImUserGroupInfoResponseDto imFriendGroupInfo = imUserGroupInfoService.selectDefGroupOne(friendId);
		if(imFriendGroupInfo == null ){
			logger.info(" 该好友默认组信息不存在 !!! friendId = {}",friendId);
			return false;
		}
		//获取好友，分组的最大排序sort
		ImUserFriendShipResponseDto imFriendShip = imUserFriendShipService.selectOneByUserIdAndGroupId( friendId, imFriendGroupInfo.getId());
		int fridensort = 0;
		if(imFriendShip != null){
			fridensort = imFriendShip.getSort() + 1;
		}
		//创建好友与用户组关系
		ImUserFriendShipRequestDto imFriendShipRequestDto = ImUserFriendShipRequestDto.build()
				.toUserId(friendId)
				.toFriendId(userId)
				.toUserGroupName(imFriendGroupInfo.getGroupName())
				.toUserGroupId(imFriendGroupInfo.getId())
				.toSort(fridensort)
				.toStatus(TbStatusEnum.ENABLE.index())
				.toRemarks(remark)//备注
				.toFriendRemarks(userInfoResponseDto.getUserName());//好友备注名
		imUserFriendShipService.saveImUserFriendShip(imFriendShipRequestDto);

		//修改好友申请状态
		ImJoinFriendStatusRequestDto imJoinFriendStatus = ImJoinFriendStatusRequestDto.build();
		imJoinFriendStatus
				.toJoinStatus(1)//0.申请 1.同意  2.拒绝,3.删除
				.toSendUserId(friendId)//好友
				.toToId(userId);//用户
		imJoinFriendService.updateImJoinFriendStatus ( imJoinFriendStatus);

		//2.用户与好友关系操作
		//获取某个用户，分组的最大排序sort
		ImUserFriendShipResponseDto imUserFriendShip = imUserFriendShipService.selectOneByUserIdAndGroupId( userId, imUserGroupInfoResponseDto.getId());
		int sort = 0;
		if(imUserFriendShip != null){
			sort = imUserFriendShip.getSort() + 1;
		}
		//创建好友与组关系
		ImUserFriendShipRequestDto imUserFriendShipRequestDto = ImUserFriendShipRequestDto.build()
				.toUserId(userId)
				.toFriendId(friendId)
				.toUserGroupName(imUserGroupInfoResponseDto.getGroupName())
				.toUserGroupId(imUserGroupInfoResponseDto.getId())
				.toSort(sort)
				.toStatus(TbStatusEnum.ENABLE.index())
				.toRemarks(remark)//备注
				.toFriendRemarks(userFriendInfoResponseDto.getUserName());//好友备注名
		ImUserFriendShipResponseDto imUserFriendShipResponseDto = imUserFriendShipService.saveImUserFriendShip(imUserFriendShipRequestDto);
		if(imUserFriendShipResponseDto == null){
			logger.info(" 绑定用户与好友信息失败 !!! ");
			return false;
		}
		//绑定用户与好友关系成功
		logger.info(" 绑定用户与好友信息成功 !!! ");
		return true;
	}

	/**
	 * 保存聊天记录
	 * @param message
	 * @param agreeVo
	 * @param enums
	 * @return
	 */
	private boolean saveMessage(ChatMessageBody message, AgreeFriendRequestVo agreeVo, ChatMessageEnum enums){
		//content 内容就是用户名称，多个有逗号分隔
		String content = SensitiveWordHelper.replace(message.getContent());
		message.setMine(false);
		message.setMessageType(enums.getDbValue());//单聊
		message.setServiceTime(new Date());
		message.setGlobalId(GlobalId.get().nextId());
		message.setMessageId(message.getToId());
		message.setReadStatus(0);//未读
		message.setType(ImMessageTypeEnum.AGREE_FRIEND.getKey());
		if(StringUtils.isEmpty(content)){
			//单人
			message.setContent("你们已经成为联系人，可以开始聊天了");
		}

		//todo 保存聊天记录;
		ImChatMessageRequestDto chatRequestDto = ImChatMessageRequestDto.build().clone(message);
		ImChatMessageResponseDto result = imChatMessageService.saveImChatMessage(chatRequestDto);
		if(null == result){
			logger.info(" 保存聊天记录失败 !!! ");
			return false;
		}
		return true;
	}

	private void saveRedis(ChatMessageBody message) {
		String messageJson  = JsonUtils.toJson(message);
		String formKey = RedisUtil.formatKey(RedisKeys.MQ_CONSUMER, message.getSendUserId());
		redisClusterServer.hmset(formKey , String.valueOf(message.getToId()), messageJson);

		String toKey = RedisUtil.formatKey(RedisKeys.MQ_CONSUMER, message.getToId());
		redisClusterServer.hmset(toKey , String.valueOf(message.getSendUserId()), messageJson);
	}
}
